package io.kiki.stack.http.feign;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

import static io.kiki.stack.http.feign.Util.*;

/**
 * Client that supports a {@link java.net.Proxy}.
 */
public class ProxiedDefaultClient extends DefaultClient {

    public static final String PROXY_AUTHORIZATION = "Proxy-Authorization";
    private final Proxy proxy;
    private String credentials;

    public ProxiedDefaultClient(SSLSocketFactory sslContextFactory, HostnameVerifier hostnameVerifier, Proxy proxy) {
        super(sslContextFactory, hostnameVerifier);
        checkNotNull(proxy, "a proxy is required.");
        this.proxy = proxy;
    }

    public ProxiedDefaultClient(SSLSocketFactory sslContextFactory, HostnameVerifier hostnameVerifier, Proxy proxy, String proxyUser, String proxyPassword) {
        this(sslContextFactory, hostnameVerifier, proxy);
        checkArgument(isNotBlank(proxyUser), "proxy user is required.");
        checkArgument(isNotBlank(proxyPassword), "proxy password is required.");
        this.credentials = basic(proxyUser, proxyPassword);
    }

    @Override
    public HttpURLConnection getConnection(URL url) throws IOException {
        HttpURLConnection connection = (HttpURLConnection) url.openConnection(this.proxy);
        if (isNotBlank(this.credentials)) {
            connection.addRequestProperty(PROXY_AUTHORIZATION, this.credentials);
        }
        return connection;
    }

    public String getCredentials() {
        return this.credentials;
    }

    private String basic(String username, String password) {
        String token = username + ":" + password;
        byte[] bytes = token.getBytes(StandardCharsets.ISO_8859_1);
        String encoded = Base64.getEncoder().encodeToString(bytes);
        return "Basic " + encoded;
    }
}
